home *** CD-ROM | disk | FTP | other *** search
- /*
- * FLMaca.c - FaceLift routines for reading MACA (MacWrite) files.
- */
-
- # include "FLFileStuff.h"
- # include "FLMaca.h"
- # include "FaceLift.h"
-
-
- /* ------------------------------------------------------------ */
- /* Global variables */
- /* ------------------------------------------------------------ */
-
-
- /*
- * File variables
- */
-
-
- Int16 macaFRef; /* file descriptor */
- Str255 macaName; /* file name */
- Int16 macaRefNum; /* volume reference number */
- Int32 paraFilePos; /* position of last paragraph read */
-
-
- /*
- * Document globals
- */
-
-
- Int16 version; /* version number */
- Int16 paraOffset; /* offset to paragraph information */
- Int16 mainParas; /* main doc paragraph count */
- Int16 headParas; /* header paragraph count */
- Int16 footParas; /* footer paragraph count */
-
-
- /*
- * Window variables - these are synchronized to only one window
- * at a time
- */
-
- Int32 infoPos; /* position of information array */
- Int16 infoLen; /* length of information array */
- Int16 activeFont; /* font active when saved */
- ActiveFace activeFace; /* face active when saved */
-
-
- /*
- * Pointers to the window variable structures for each window
- */
-
- Windows3 *headWind3, *footWind3, *mainWind3;
- Windows6 *headWind6, *footWind6, *mainWind6;
-
-
- /*
- * Structures for holding document information for each
- * supported version of MacWrite
- */
-
- DocInfo3 docInfo3;
- DocInfo6 docInfo6;
-
-
- /*
- * Miscellaneous
- */
-
-
- Handle paraBuf = nil; /* buffer for contents of paragraph */
- Int16 totalParas; /* total paragraphs in document */
- Int16 paraNum; /* current paragraph number */
- Int16 paraDocType; /* whether main, header or footer para */
- Int16 paraType; /* paragraph type (text, ruler, picture) */
- Int16 paraLen; /* paragraph length */
- Int16 textLen; /* length of text in text paragraphs */
- Int16 formats; /* number of formats in text paragraph */
- Int16 fmtOffset; /* offset w/in text paragraph to formats */
- InfoArray6 **paraInfo6 = nil; /* info array (for version 6 only) */
-
-
-
- /* ------------------------------------------------------------ */
- /* Local variables */
- /* ------------------------------------------------------------ */
-
- static Int16 paraIndex; /* paragraph index w/in document window */
- static Point dlogWhere = { 70, 100 }; /* SFGetFile position */
-
-
-
- /* ------------------------------------------------------------ */
- /* Document structure -> program variable conversion routines */
- /* ------------------------------------------------------------ */
-
-
- /*
- * Convert version 3 globals to unstructured variables
- */
-
-
-
- void
- GUnstruct3 (Globals3 *g)
- {
- paraOffset = g->paraOffset;
- mainParas = g->mainParas;
- headParas = g->headParas;
- footParas = g->footParas;
- }
-
-
- /*
- * Convert version 3 window variables to unstructured variables
- * *for one document window only*.
- */
-
- void
- WUnstruct3 (Windows3 *w)
- {
- activeFont = w->activeFont;
- activeFace = w->activeFace;
- }
-
-
- /*
- * Convert version 6 globals to unstructured variables
- */
-
- void
- GUnstruct6 (Globals6 *g)
- {
- mainParas = g->mainParas;
- headParas = g->headParas;
- footParas = g->footParas;
- }
-
-
- /*
- * Convert version 6 window variables to unstructured variables
- * *for one document window only*.
- */
-
- void
- WUnstruct6 (Windows6 *w)
- {
- infoPos = w->infoPos;
- infoLen = w->infoLen;
- activeFace = w->activeFace;
- activeFont = w->activeFont;
- }
-
-
-
- /* ------------------------------------------------------------ */
- /* Input routines */
- /* ------------------------------------------------------------ */
-
-
- /*
- * Open MacWrite file. Return error code as function result.
- * The mode is fsRdPerm if the file is simply being read, fsRdWrPerm
- * if it's being converted in place.
- *
- * Since every subsequent operation needs to know the version
- * number, that is immediately determined as well. Also get
- * document information for the current input file, sync the
- * globals and set up the window var pointers. Initialize variables
- * used for paragraph streaming. totalParas is set to the total of all
- * the paragraphs in the entire document. It can be reset to mainParas
- * after the GetDocInfo call if the calling operation only wants to
- * stream the main document paragraphs and skip the header and footer
- * paragraphs.
- */
-
- Boolean
- OpenMaca (StringPtr fName, int vRefNum)
- {
- Boolean result = true;
- OSErr err;
-
- CopyString (fName, macaName);
- macaRefNum = vRefNum;
- if ((err = FSOpen (macaName, macaRefNum, &macaFRef)) != noErr)
- {
- FileErr (err);
- return (false);
- }
-
- /*
- * File opened OK - determine version and do version-specific setup
- */
-
- FileSeek (macaFRef, 0L); /* version's in the first word */
- (void) FileRead (macaFRef, (Ptr) &version, (Int32) sizeof (Int16));
- FileSeek (macaFRef, 0L); /* go back to beginning */
-
- switch (version)
- {
-
- case version3:
- (void) FileRead (macaFRef, (Ptr) &docInfo3, (Int32) sizeof (DocInfo3));
- GUnstruct3 (&docInfo3.globals3);
- mainWind3 = &docInfo3.mainWind3;
- headWind3 = &docInfo3.headWind3;
- footWind3 = &docInfo3.footWind3;
- paraBuf = NewHandle (0L);
- totalParas = mainParas + headParas + footParas;
- paraNum = -1;
- break;
-
- case version6:
- (void) FileRead (macaFRef, (Ptr) &docInfo6, (Int32) sizeof (DocInfo6));
- GUnstruct6 (&docInfo6.globals6);
- mainWind6 = &docInfo6.mainWind6;
- headWind6 = &docInfo6.headWind6;
- footWind6 = &docInfo6.footWind6;
- paraBuf = NewHandle (0L);
- paraInfo6 = (InfoArray6 **) NewHandle (0L);
- totalParas = mainParas + headParas + footParas;
- paraNum = -1;
- break;
-
- default:
- Message3 ("\p\"", macaName, "\p\": Unsupported version of MacWrite");
- CloseMaca ();
- result = false;
- break;
-
- }
-
- return (result);
- }
-
-
- /*
- * Close MacWrite file and release any associated storage.
- */
-
- void
- CloseMaca (void)
- {
- (void) FSClose (macaFRef);
- (void) FlushVol (nil /*macaFRef*/, macaRefNum);
-
- if (paraBuf != nil)
- {
- DisposeHandle (paraBuf);
- paraBuf = nil;
- }
- if (paraInfo6 != nil)
- {
- DisposeHandle ((Handle) paraInfo6);
- paraInfo6 = nil;
- }
- }
-
-
- static Boolean
- ReadParaBuf (Int16 pLen)
- {
- Str255 s;
- Boolean result = false;
-
- SetHandleSize (paraBuf, (Int32) pLen); /* make big enough */
- if (MemError () != noErr)
- {
- NumToString ((long) pLen, s);
- Message3 ("\pCan't read paragraph (memory error). Trying to read ",
- s, "\p bytes");
- }
- else
- {
- GetFPos (macaFRef, ¶FilePos); /* remember paragraph position */
- HLock (paraBuf);
- result = FileRead (macaFRef, *paraBuf, (Int32) pLen);
- HUnlock (paraBuf);
- }
- return (result);
- }
-
-
- /*
- * Read next version 3 paragraph.
- */
-
- static Boolean
- ReadPara3 (void)
- {
- if (paraNum == 0) /* set position on first paragraph */
- FileSeek (macaFRef, (Int32) paraOffset);
-
- if (FileRead (macaFRef, (Ptr) ¶Type, (Int32) sizeof (Int16))
- && FileRead (macaFRef,(Ptr) ¶Len, (Int32) sizeof (Int16))
- && ReadParaBuf (paraLen))
- {
- if (paraType == textPara)
- {
- textLen = * (Int16 *) *paraBuf; /* number of text bytes */
- fmtOffset = ((textLen + 1) & ~1) + 2;
- formats = * (Int16 *) (*paraBuf + fmtOffset) / sizeof (Format);
- fmtOffset += 2;
- }
- return (true);
- }
- return (false);
- }
-
-
- /*
- * Sync to window variables and read in paragraph info array
- * for document corresponding to window (main, header, footer).
- */
-
- static Boolean
- GetInfoArray (Windows6 *w)
- {
- Str255 s;
- Boolean result = false;
-
- WUnstruct6 (w); /* sync window vars */
- SetHandleSize ((Handle) paraInfo6, (Int32) infoLen); /* make big enough */
- if (MemError () != noErr)
- {
- NumToString ((long) infoLen, s);
- Message3 ("\pCan't read paragraph info (memory error). Trying to read ",
- s, "\p bytes");
- }
- else
- {
- FileSeek (macaFRef, (Int32) infoPos); /* seek to information array */
- HLock ((Handle) paraInfo6);
- result = FileRead (macaFRef, (Ptr) *paraInfo6, (Int32) infoLen); /* read it */
- HUnlock ((Handle) paraInfo6);
- paraIndex = -1;
- }
- return (result);
- }
-
-
- /*
- * Read next version 6 paragraph.
- *
- * If this is the first paragraph of the main, header or footer
- * document, sync to the window variables for the correct document
- * and read in the paragraph info array.
- *
- * If the paragraph contains compressed text, textLen is the number
- * of *uncompressed* chars in the paragraph, so have to figure out
- * how many bytes the text actually take up in order to find the
- * format information.
- */
-
- static Boolean
- ReadPara6 (void)
- {
- ParaInfo6 info;
- Boolean result = true;
- int count;
- Boolean firstHalf;
- Byte *p;
- int nibble;
-
- if (paraNum == 0) /* first paragraph of main? */
- result = GetInfoArray (mainWind6);
- else if (paraNum == mainParas) /* first paragraph of head? */
- result = GetInfoArray (headWind6);
- else if (paraNum == mainParas + headParas) /* first paragraph of foot? */
- result = GetInfoArray (footWind6);
-
- if (result == false)
- return (false); /* couldn't read info array - trouble! */
-
- info = (**paraInfo6)[++paraIndex];
- paraType = info.paraHeight;
- if (paraType < 0)
- paraType = pictPara;
- else if (paraType == 0)
- paraType = rulerPara;
- else
- paraType = textPara;
-
- paraLen = info.paraLen;
-
- FileSeek (macaFRef, info.paraStOff.paraOffset & 0x00ffffff);
-
- if (ReadParaBuf (paraLen) == false)
- return (false);
-
- if (paraType == textPara)
- {
- textLen = * (Int16 *) *paraBuf; /* number of text bytes */
- if ((info.paraStOff.paraStatus & stCompress) == 0)
- {
- fmtOffset = ((textLen + 1) & ~1) + 2; /* uncompressed */
- }
- else
- {
- HLock (paraBuf);
- p = (Byte *) (*paraBuf + 2);
- count = 0;
- firstHalf = true;
- while (count < textLen)
- {
- if (firstHalf)
- nibble = ((Byte) *p) >> 4;
- else
- nibble = *p++ & 0x0f;
- if (nibble == 15)
- ++p;
- firstHalf = !firstHalf;
- ++count;
- }
- if (!firstHalf) /* want p to end up on first byte */
- ++p; /* past end of compressed text */
-
- fmtOffset = ((char *) p - *paraBuf + 1) & ~1;
- HUnlock (paraBuf);
- }
-
- formats = * (Int16 *) (*paraBuf + fmtOffset) / sizeof (Format);
- fmtOffset += 2;
- }
-
- return (true);
- }
-
-
- /*
- * Read a paragraph. Returns false if it couldn't be read, or if at
- * end of file. Sets paraDocType to the document type (main, header,
- * footer).
- *
- * The paragraphs are read in the order: main, header, footer. This
- * order is dictated by the file structure for version 3 and for
- * consistency is mimicked for version 6 files (see ReadPara6).
- *
- * If the paragraph is a text paragraph, get the text length (in first
- * two bytes), and the format offset (in the two bytes on the word
- * boundary following the text. The format offset is left pointing to
- * the actual format data, not the format length word immediately
- * preceding.
- */
-
- Boolean
- ReadPara (void)
- {
- Boolean result;
-
- if (++paraNum >= totalParas)
- return (false);
-
- if (paraNum < mainParas)
- paraDocType = mainDoc;
- else if (paraNum < mainParas + headParas)
- paraDocType = headDoc;
- else
- paraDocType = footDoc;
-
- switch (version)
- {
-
- case version3:
- result = ReadPara3 ();
- break;
-
- case version6:
- result = ReadPara6 ();
- break;
-
- }
-
- return (result);
- }
-